use std::fs::File;
use std::io::{Write};

use tera::{Tera, Context};

use crate::Result;
use crate::cobol::{Record, RecordLike};

pub fn render_module(root_record: Record,
                 cpy_name: &str,
                 file_name: Option<&str>,
                 tera: &Tera) -> Result<()>{
    let mut fields = Vec::new();
    root_record.collect_fields_into(&mut fields);
    let total_length = root_record.length();
    let mut struct_name = String::new();
    for (i, c) in cpy_name.chars().enumerate(){
        if c == '.' {
            break;
        } else {
            if i == 0 {
                struct_name.push(c.to_ascii_uppercase());
            } else {
                struct_name.push(c.to_ascii_lowercase());
            }
        }
    }

    let mut inits = Vec::new();
    let mut getters = Vec::new();
    let mut field_names = Vec::new();
    for field in fields { 
        inits.push(field.render_init(&tera));
        getters.push(field.render_getter(&tera));
        field_names.push(field.name().to_lowercase().replace("-", "_").to_owned());
    }
    let mut context = Context::new();
    context.insert("total_length", &total_length);
    context.insert("inits", &inits);
    context.insert("struct_name", &struct_name);
    context.insert("getters", &getters);
    context.insert("field_names", &field_names);
    let module = tera.render("module.tera", &context)?;
    if let Some(file_name) = file_name {
        let mut f = File::create(file_name)?;
        write!(f, "{}", module)?;
    } else {
        println!("{}", module);
    }
    Ok(())
}
